﻿using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace revitDemo
{
    public abstract class RevietBase
    {
        public readonly ExternalCommandData _commandData;

        //uidoc.RefreshActiveView();
        // SolidOptions options = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

        public SolidOptions Options { get {return new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId); } }

        public UIDocument Uidoc
        {
            get
            {
                if (_commandData != null)
                {
                    return _commandData.Application.ActiveUIDocument;
                }
                return null;
            }
        }
        public Document Doc
        {
            get
            {
                if (Uidoc != null)
                {
                    return Uidoc.Document;
                }
                return null;
            }
        }

        public RevietBase(ExternalCommandData commandData)
        {
            _commandData=commandData;
        }


        public void OpenTransaction(string name, Action<Document> action)
        {
            try
            {
                var document = Uidoc.Document;
                using (Transaction t = new Transaction(document, name))
                {
                    t.Start();
                    action(document);
                    t.Commit();
                    Uidoc.RefreshActiveView();//刷新视图
                }
            }
            catch (Exception ex)
            {
                TaskDialog.Show("错误提示", $"{ex.Message}");
                throw;
            }

        }

        //    DirectShape ds = DirectShape.CreateElement(Command.Doc, new ElementId(BuiltInCategory.OST_GenericModel));
        //    ds.SetShape(new GeometryObject[] { cone
        //});


        public void OpenTransaction(string name, Solid solid)
        {
            try
            {
                var document = Uidoc.Document;
                using (Transaction t = new Transaction(document, name))
                {
                    t.Start();
                    DirectShape ds = DirectShape.CreateElement(document, new ElementId(BuiltInCategory.OST_GenericModel));
                    ds.SetShape(new GeometryObject[] { solid });
                    t.Commit();
                    Uidoc.RefreshActiveView();//刷新视图
                }
            }
            catch (Exception ex)
            {
                TaskDialog.Show("错误提示", $"{ex.Message}");
                throw;
            }

        }




        /// <summary>
        /// TransactionGroup用来将几个独立的事务分组，这样一个组可以同时处理许多事务。 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="action"></param>
        public void OpenTransactionGroup(string name, Action<Document> action)
        {
            var document = Uidoc.Document;
            using (TransactionGroup tGroup = new TransactionGroup(document, name))
            {
                try
                {
                    tGroup.Start();
                    action(document);
                    tGroup.Assimilate();
                }
                catch (Exception ex)
                {
                    tGroup.RollBack();
                }
            }

        }



        public Solid Intersect(Solid solid1, Solid solid2)
        {
            return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Intersect);
        }
        public Solid Union(Solid solid1, Solid solid2)
        {
            return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Union);
        }
        public Solid Difference(Solid solid1, Solid solid2)
        {
            return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Difference);
        }




        public void 坐标系()
        {
            var x = Line.CreateBound(XYZ.Zero, new XYZ(100, 0, 0));
            var y = Line.CreateBound(XYZ.Zero, new XYZ(0, 100, 0));
            var z = Line.CreateBound(XYZ.Zero, new XYZ(0, 0, 100));
            OpenTransaction("bb", s =>
            {
                x.CreateModelCurve(s);
                y.CreateModelCurve(s);
                z.CreateModelCurve(s);
            });

        }


        public abstract void Test();


        /// <summary>
        /// 圆柱
        /// </summary>
        /// <param name="center"></param>
        /// <param name="bottomradius"></param>
        /// <param name="height"></param>
        /// <param name="cylinderdirection"></param>
        /// <returns></returns>
        public Solid CreateCylinder(XYZ center, double bottomradius, double height, CylinderDirection cylinderdirection)
        {
            double halfheight = height / 2.0;
            XYZ bottomcenter = new XYZ(
               cylinderdirection == CylinderDirection.BasisX ? center.X - halfheight : center.X,
               cylinderdirection == CylinderDirection.BasisY ? center.Y - halfheight : center.Y,
               cylinderdirection == CylinderDirection.BasisZ ? center.Z - halfheight : center.Z);
            XYZ topcenter = new XYZ(
               cylinderdirection == CylinderDirection.BasisX ? center.X + halfheight : center.X,
               cylinderdirection == CylinderDirection.BasisY ? center.Y + halfheight : center.Y,
               cylinderdirection == CylinderDirection.BasisZ ? center.Z + halfheight : center.Z);

            CurveLoop sweepPath = new CurveLoop();
            sweepPath.Append(Line.CreateBound(bottomcenter, topcenter));

            List<CurveLoop> profileloops = new List<CurveLoop>();
            CurveLoop profileloop = new CurveLoop();
            var cemiEllipse1 = Ellipse.CreateCurve(bottomcenter, bottomradius, bottomradius,
               cylinderdirection == CylinderDirection.BasisX ? Autodesk.Revit.DB.XYZ.BasisY : Autodesk.Revit.DB.XYZ.BasisX,
               cylinderdirection == CylinderDirection.BasisZ ? Autodesk.Revit.DB.XYZ.BasisY : Autodesk.Revit.DB.XYZ.BasisZ,
               -Math.PI, 0);
            var cemiEllipse2 = Ellipse.CreateCurve(bottomcenter, bottomradius, bottomradius,
               cylinderdirection == CylinderDirection.BasisX ? Autodesk.Revit.DB.XYZ.BasisY : Autodesk.Revit.DB.XYZ.BasisX,
               cylinderdirection == CylinderDirection.BasisZ ? Autodesk.Revit.DB.XYZ.BasisY : Autodesk.Revit.DB.XYZ.BasisZ,
               0, Math.PI);
            profileloop.Append(cemiEllipse1);
            profileloop.Append(cemiEllipse2);
            profileloops.Add(profileloop);
            return GeometryCreationUtilities.CreateSweptGeometry(sweepPath, 0, 0, profileloops);
        }

        /// <summary>
        /// 方块
        /// </summary>
        /// <param name="center"></param>
        /// <param name="l"></param>
        /// <returns></returns>
        public Solid CreateBox(XYZ center, double l)
        {
            var LHalf = l / 2;
            List<CurveLoop> curves = new List<CurveLoop>();
            CurveLoop curve = new CurveLoop();
            curve.Append(Line.CreateBound(new XYZ(center.X - LHalf, center.Y - LHalf, center.Z - LHalf), new XYZ(center.X - LHalf, center.Y + LHalf, center.Z - LHalf)));
            curve.Append(Line.CreateBound(new XYZ(center.X - LHalf, center.Y + LHalf, center.Z - LHalf), new XYZ(center.X + LHalf, center.Y + LHalf, center.Z - LHalf)));
            curve.Append(Line.CreateBound(new XYZ(center.X + LHalf, center.Y + LHalf, center.Z - LHalf), new XYZ(center.X + LHalf, center.Y - LHalf, center.Z - LHalf)));
            curve.Append(Line.CreateBound(new XYZ(center.X + LHalf, center.Y - LHalf, center.Z - LHalf), new XYZ(center.X - LHalf, center.Y - LHalf, center.Z - LHalf)));
            curves.Add(curve);
            XYZ extrusiondir = new XYZ(0, 0, 1); // orthogonal
            return GeometryCreation.Instance.CreateExtrusion(curves, extrusiondir, l);
        }



    }







    /***
     * UiDoc 方法
     *      uidoc.GetOpenUIViews()    //返回所有打开的视图
            uidoc.CanPlaceElementType() //当前视图是否可以防止该类型构件
            uidoc.PostRequestForElementTypePlacement()  //放置一个elementtype的实例
            uidoc.RefreshActiveView()   //刷新当前视图
            uidoc.RequestViewChange()   //切换另一个 视图为 激活状态
            uidoc.SaveAndClose()    //保存并关闭
            uidoc.SaveAs()  //另存为
            uidoc.Selection()   // 让用户去选择各种东西
            uidoc.Selection.PickBox  //pick系列
            uidoc.Selection.PickObject // 选一个物体
            https://blog.csdn.net/zyandyz001/article/details/121142735
     * 
     *      System.Diagnostics.Process.Start("http://www.baidu.com/");  // 打开网页
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * *****/




}
